package com.utooo.service.purchase;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.repository.AbstractRepository;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.utooo.constant.ResultCodeConstant;
import com.utooo.dao.purchase.DemandMaterialDetailMapper;
import com.utooo.dao.purchase.PurchaseOrderMapper;
import com.utooo.dao.purchase.PurchaseTaskManagementMapper;
import com.utooo.dao.purchase.TaskMergeWellRuleMapper;
import com.utooo.dao.purchase.requirement.PurchaseRequirementMapper;
import com.utooo.pojo.domain.purchase.DemandMaterialDetailDO;
import com.utooo.pojo.domain.purchase.order.PurchaseOrderDO;
import com.utooo.pojo.domain.purchase.requirement.PurchaseRequirementDO;
import com.utooo.pojo.domain.purchase.task.PurchaseTaskManagementDO;
import com.utooo.pojo.domain.purchase.task.TaskMergeWellRuleDO;
import com.utooo.pojo.dto.common.RestResult;
import com.utooo.pojo.dto.purchase.DemandMaterialDetailDTO;
import com.utooo.pojo.dto.purchase.order.PurchaseOrderDTO;
import com.utooo.pojo.dto.purchase.task.PurchaseTaskCombinedDTO;
import com.utooo.pojo.dto.purchase.task.PurchaseTaskTransferDTO;
import com.utooo.pojo.enums.PurchaseTaskStatus;
import com.utooo.pojo.vo.purchase.DemandMaterialDetailVO;
import com.utooo.util.GenerateReceiptNo;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.utooo.constant.Constans.IGNORED_PROPERTIES;

@Slf4j
@Service
@RequiredArgsConstructor
public class PurchaseTaskManagementServiceImpl
        extends ServiceImpl<PurchaseTaskManagementMapper, PurchaseTaskManagementDO>
        implements PurchaseTaskManagementService {

    @Resource
    private TaskMergeWellRuleMapper taskMergeWellRuleMapper;

    @Resource
    private PurchaseTaskManagementMapper purchaseTaskManagementMapper;

    @Resource
    private DemandMaterialDetailMapper demandMaterialDetailMapper;
    @Resource
    private DemandMaterialDetailService demandMaterialDetailService;
    @Resource
    private PurchaseOrderService purchaseOrderService;
    private final PurchaseRequirementMapper purchaseRequirementMapper;
    @Override
    public Boolean isCombined(String taskIds) {
        List<String> taskIdList = StrUtil.split(taskIds, StrUtil.COMMA);
        if (CollUtil.isEmpty(taskIdList)) {
            log.error("任务id为空，taskIds:{}", taskIds);
            return false;
        }
        if (taskIdList.size() == 1) {
            log.info("任务数量为1，不需要合并，taskIds:{}", taskIds);
            return true;
        }
        List<PurchaseTaskCombinedDTO> tasks =
                purchaseTaskManagementMapper.getCombinedPurchaseTasks(taskIdList);
        if (CollUtil.isEmpty(tasks)) {
            log.error("任务不存在，taskIds:{}", taskIds);
            return false;
        }
        Set<String> companyIds = tasks.stream()
                .map(PurchaseTaskCombinedDTO::getCompany)
                .collect(Collectors.toSet());
        if (CollUtil.isEmpty(companyIds)) {
            log.error("采购任务所属公司为空，taskIds:{}", taskIds);
            return false;
        }

        if (companyIds.size() > 1) {
            log.error("任务不属于同一个公司，taskIds:{}", taskIds);
            return false;
        }
        List<TaskMergeWellRuleDO> rules =
                taskMergeWellRuleMapper.selectList(new LambdaQueryWrapper<TaskMergeWellRuleDO>()
                        .eq(TaskMergeWellRuleDO::getCompany, new ArrayList<>(companyIds).get(0))
                        .orderByAsc(TaskMergeWellRuleDO::getPriority)
                        .last("limit 1"));
        if (CollUtil.isEmpty(rules)) {
            log.info("没有找到合并规则，taskIds:{}", taskIds);
            return true;
        }
        TaskMergeWellRuleDO rule = rules.get(0);
        String currency = rule.getCurrency();
        if ("1".equals(currency)) {
            Set<String> currencyList = tasks.stream()
                    .map(PurchaseTaskCombinedDTO::getCurrency)
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(currencyList) && currencyList.size() > 1) {
                log.error("任务的币种不一致，不能合并，taskIds:{}", taskIds);
                return false;
            }
        }

        String demandNo = rule.getDemandNo();
        if ("1".equals(demandNo)) {
            Set<String> demandNoList = tasks.stream()
                    .map(PurchaseTaskCombinedDTO::getDemandNo)
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(demandNoList) && demandNoList.size() > 1) {
                log.error("任务的需求编码不一致，不能合并，taskIds:{}", taskIds);
                return false;
            }
        }
        String materialNo = rule.getMaterialNo();
        if ("1".equals(materialNo)) {
            Set<String> materialNoList = tasks.stream()
                    .map(PurchaseTaskCombinedDTO::getMaterialNo)
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(materialNoList) && materialNoList.size() > 1) {
                log.error("任务的物料编码不一致，不能合并，taskIds:{}", taskIds);
                return false;
            }
        }
        String categoryNo = rule.getCategoryNo();
        if ("1".equals(categoryNo)) {
            Set<String> categoryNoList = tasks.stream()
                    .map(PurchaseTaskCombinedDTO::getCategoryNo)
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(categoryNoList) && categoryNoList.size() > 1) {
                log.error("任务的品类编码不一致，不能合并，taskIds:{}", taskIds);
                return false;
            }
        }
        String brand = rule.getBrand();
        if ("1".equals(brand)) {
            Set<String> brandList = tasks.stream()
                    .map(PurchaseTaskCombinedDTO::getBrand)
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(brandList) && brandList.size() > 1) {
                log.error("任务的品牌不一致，不能合并，taskIds:{}", taskIds);
                return false;
            }
        }
        String purchaser = rule.getPurchaser();
        if ("1".equals(purchaser)) {
            Set<String> purchaserList = tasks.stream()
                    .map(PurchaseTaskCombinedDTO::getPurchaser)
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(purchaserList) && purchaserList.size() > 1) {
                log.error("任务的采购员不一致，不能合并，taskIds:{}", taskIds);
                return false;
            }
        }
        String demandDepartment = rule.getDemandDepartment();
        if ("1".equals(demandDepartment)) {
            Set<String> demandDepartmentList = tasks.stream()
                    .map(PurchaseTaskCombinedDTO::getDemandDepartment)
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(demandDepartmentList) && demandDepartmentList.size() > 1) {
                log.error("任务的需求部门不一致，不能合并，taskIds:{}", taskIds);
                return false;
            }
        }
        String demandType = rule.getDemandType();
        if ("1".equals(demandType)) {
            Set<String> demandTypeList = tasks.stream()
                    .map(PurchaseTaskCombinedDTO::getDemandType)
                    .collect(Collectors.toSet());

            if (CollUtil.isNotEmpty(demandTypeList) && demandTypeList.size() > 1) {
                log.error("任务的需求类型不一致，不能合并，taskIds:{}", taskIds);
                return false;
            }
        }
        return true;
    }

    @Override
    public List<DemandMaterialDetailVO> getMaterialListByTaskIds(String taskIds) {
        List<String> taskIdList = StrUtil.split(taskIds, StrUtil.COMMA);
        if (CollUtil.isEmpty(taskIdList)) {
            log.error("任务id为空，taskIds:{}", taskIds);
            return new ArrayList<>();
        }
        return purchaseTaskManagementMapper.getMaterialListByTaskIds(taskIdList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<String> addOrder(PurchaseOrderDTO purchaseOrderDTO) {
        // 参数校验
        if (purchaseOrderDTO == null || purchaseOrderDTO.getDemandMaterialDetailList() == null) {
            return new RestResult<>(ResultCodeConstant.CODE_400, "PurchaseOrderDTO or its detail list cannot be null");
        }
        List<DemandMaterialDetailDTO> demandMaterialDetailList = purchaseOrderDTO.getDemandMaterialDetailList();
        Map<String, Integer> materialDemandQuantityMap =
                demandMaterialDetailList
                        .stream()
                        .filter(i -> i.getDemandQuantity() != null)
                        .collect(Collectors.toMap(DemandMaterialDetailDTO::getTaskId,
                                DemandMaterialDetailDTO::getDemandQuantity, (k1, k2) -> k1));
        List<PurchaseTaskManagementDO> tasks = this.listByIds(materialDemandQuantityMap.keySet());
        Map<String, PurchaseTaskManagementDO> taskMap = new HashMap<>();
        if (CollUtil.isNotEmpty(tasks)) {
            taskMap = tasks.stream()
                    .collect(Collectors.toMap(PurchaseTaskManagementDO::getId, Function.identity(), (k1, k2) -> k1));
            for (Map.Entry<String, Integer> entry : materialDemandQuantityMap.entrySet()) {
                String k = entry.getKey();
                Integer v = entry.getValue();
                PurchaseTaskManagementDO task = taskMap.get(k);
                if (task != null) {
                    Integer pendingAcceptanceQuantity = task.getPendingAcceptanceQuantity();
                    if (pendingAcceptanceQuantity != null && v > pendingAcceptanceQuantity) {
                        return new RestResult<>(ResultCodeConstant.CODE_400, "The demand quantity cannot be greater than the pending accept quantity");
                    }
                }
            }
        }
        PurchaseOrderDO purchaseOrderDO = new PurchaseOrderDO();
        BeanUtil.copyProperties(purchaseOrderDTO, purchaseOrderDO);
        // 生成规则：PO+日期时间（年月日）+3位数（从001开始）
        String orderNo = purchaseOrderService.generateOrderNo();
        purchaseOrderDO.setOrderNo(orderNo);
        purchaseOrderService.save(purchaseOrderDO);

        List<DemandMaterialDetailDO> demandMaterialDetails = BeanUtil.copyToList(demandMaterialDetailList, DemandMaterialDetailDO.class);
        demandMaterialDetails.forEach(i -> i.setForeignId(purchaseOrderDO.getId()));
        demandMaterialDetailService.saveBatch(demandMaterialDetails);
        if (CollUtil.isNotEmpty(tasks)) {
            Map<String, PurchaseTaskManagementDO> finalTaskMap = taskMap;
            materialDemandQuantityMap.forEach((k, v) -> {
                PurchaseTaskManagementDO task = finalTaskMap.get(k);
                if (task != null) {
                    Integer pendingAcceptanceQuantity = task.getPendingAcceptanceQuantity();
                    if (pendingAcceptanceQuantity != null) {
                        Integer acceptedQuantity = task.getAcceptedQuantity();
                        if (acceptedQuantity == null) {
                            acceptedQuantity = 0;
                        }

                        if (v < pendingAcceptanceQuantity) {
                            task.setStatus(PurchaseTaskStatus.PARTIALLY_ACCEPTED.getCode());
                            task.setPendingAcceptanceQuantity(pendingAcceptanceQuantity - v);
                            task.setAcceptedQuantity(acceptedQuantity + v);
                        } else {
                            task.setStatus(PurchaseTaskStatus.ACCEPTED.getCode());
                            task.setPendingAcceptanceQuantity(0);
                            task.setAcceptedQuantity(acceptedQuantity + v);
                        }
                        this.updateById(task);
                    }
                }
            });
        }
        return new RestResult<>(ResultCodeConstant.CODE_200, ResultCodeConstant.CODE_200_MSG);
    }

    @Override
    public Boolean transferTask(PurchaseTaskTransferDTO purchaseTaskTransferDTO) {
        List<String> taskIds = purchaseTaskTransferDTO.getTaskIds();
        String purchaser = purchaseTaskTransferDTO.getPurchaser();
        if (CollUtil.isEmpty(taskIds) || StrUtil.isBlank(purchaser)) {
            throw new IllegalArgumentException("TaskIds or purchaser cannot be null");
        }
        List<PurchaseTaskManagementDO> tasks = this.listByIds(taskIds);
        if (CollUtil.isEmpty(tasks)) {
            log.error("Tasks not found for taskIds: {}", taskIds);
            return false;
        }
        tasks.forEach(i -> {
            i.setInitialPurchaser(i.getPurchaser());
            i.setPurchaser(purchaser);
        });
        this.updateBatchById(tasks);
        return true;
    }

    @Override
    public Boolean addTask(String demandId) {
        // 根据需求id查询出所有的需求数据
        PurchaseRequirementDO purchaseRequirementDO = purchaseRequirementMapper.selectById(demandId);

        log.info("--------------------------" + demandId);
        //根据需求id查询出所有的物料
        List<DemandMaterialDetailDO> materialDetailDOList = demandMaterialDetailMapper.selectList(new LambdaQueryWrapper<DemandMaterialDetailDO>().eq(DemandMaterialDetailDO::getForeignId, demandId));
        List<PurchaseTaskManagementDO> taskManagementDOList = new ArrayList<>();
        //生成任务
        materialDetailDOList.forEach(i -> {
            PurchaseTaskManagementDO taskManagementDO = new PurchaseTaskManagementDO(i);
            taskManagementDO.setTaskOrderNumber(GenerateReceiptNo.getGenerateReceiptNo("SQTK", "comInputField101", purchaseTaskManagementMapper));
            taskManagementDO.setMaterialInfo(i.getId());
            log.info("taskManagementDO:{}", i.getId());
            log.info("taskManagementDO:{}", i);
            taskManagementDO.setDemandNumber(purchaseRequirementDO.getRequirementNo());
            taskManagementDO.setCompany(purchaseRequirementDO.getCompany());
            taskManagementDO.setDemandTitle(purchaseRequirementDO.getRequirementTitle());
            taskManagementDOList.add(taskManagementDO);
        });
        // 保存
        purchaseTaskManagementMapper.insert(taskManagementDOList);
        return true;
    }
}